package com.hunttown.mes.manage.controller._erp;

import com.hunttown.mes.common.OperateCode;
import com.hunttown.mes.manage.controller.common.AdminBaseClass;
import com.hunttown.mes.manage.controller.common.ModelService;
import com.hunttown.mes.rpc.domain.AnalysisManageDTO;
import com.hunttown.mes.rpc.domain.TransportExpenseDTO;
import com.hunttown.mes.rpc.domain.WorkflowApplyLineDTO;
import com.hunttown.mes.rpc.domain.WorkflowBusinessDTO;
import com.hunttown.mes.rpc.domain.enums.expense.BXTypeEnum;
import com.hunttown.mes.rpc.domain.enums.expense.BXStatusEnum;
import com.hunttown.mes.rpc.domain.enums.pay.ReceiveWayEnum;
import com.hunttown.common.domain.Page;
import com.hunttown.mes.common.utils.*;
import com.hunttown.mes.manage.service.*;
import com.hunttown.mes.rpc.domain.query.TransportExpenseDTOQuery;
import com.hunttown.mes.rpc.domain.query.WorkflowApplyLineDTOQuery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;

import static com.hunttown.mes.common.utils.PageUtils.PagePackage;

/**
 * @title: 借款
 * @author: wangjunfu
 * @date: 2019-07-07 10:50:24
 * @description:
 */
@Controller
@RequestMapping(value = "/erp/expense-borrow")
public class ExpenseBorrowController {

    private final static Logger logger = LoggerFactory.getLogger(ExpenseBorrowController.class);

    private final TransportExpenseManageService expenseService;
    private final AnalysisManageManageService manageService;
    private final ModelService modelService;
    private final TransactionService transactionService;
    private final TransportOperateLogManageService logService;
    private final WorkflowApplyLineManageService applyLineService;
    private final WorkflowBusinessManageService businessService;
    private final WorkflowBusinessNodeManageService businessNodeService;

    @Autowired
    public ExpenseBorrowController(TransportExpenseManageService expenseService, AnalysisManageManageService manageService, ModelService modelService, TransactionService transactionService, TransportOperateLogManageService logService, WorkflowApplyLineManageService applyLineService, WorkflowBusinessManageService businessService, WorkflowBusinessNodeManageService businessNodeService) {
        this.expenseService = expenseService;
        this.manageService = manageService;
        this.modelService = modelService;
        this.transactionService = transactionService;
        this.logService = logService;
        this.applyLineService = applyLineService;
        this.businessService = businessService;
        this.businessNodeService = businessNodeService;
    }

    //region 数据列表

    /**
     * 首页
     *
     * @param model    model模型
     * @param dtoQuery 查询条件
     * @return vm
     */
    @RequestMapping(value = "/index", method = RequestMethod.GET)
    public String index(HttpServletRequest request, Model model, TransportExpenseDTOQuery dtoQuery) {

        // 显示所有（初始化或未选择的情况 1显示所有 0不显示取消数据）
        if (dtoQuery.getShowAll() == null) {
            dtoQuery.setShowAll(0);
        }
        if (dtoQuery.getShowAll() == 0) {
            dtoQuery.setStopFlag(0);
        }

        // 日期（初始化 30天）
        if (StringUtils.isBlank(dtoQuery.getDaterange())) {
            dtoQuery.setDaterange(String.format("%s ~ %s", DateConvertUtils.getPastDate(30), DateConvertUtils.getPastDate(0)));
        }

        // 只显示自己的单子（管理员可以看到所有单子，拥有权限的人也可以查看全部）（不设限制）
        //String pin = AdminBaseClass.getPin(request);
        //AnalysisManageDTO curr_obj = manageService.getFromCachePin(pin);
        //Integer canExec = modelService.getLookAlldataAuthor(pin);
        //if (canExec <= 0) { //没有权限
        //    dtoQuery.setAdminId(curr_obj.getId());
        //}

        dtoQuery.setParentId(0); //只查询主单，子单单独获取
        dtoQuery.setOrderBy("order by id desc");
        Page<TransportExpenseDTO> dataPage = expenseService.getForPage(dtoQuery);

        BigDecimal BxAmountReal = new BigDecimal(0);      //实际报销金额

        // 实时更新列表信息
        if (dataPage != null && dataPage.getItems().size() > 0) {
            WorkflowApplyLineDTOQuery lineQuery;
            WorkflowApplyLineDTO lineDTO;

            List<TransportExpenseDTO> childList;

            for (TransportExpenseDTO item : dataPage.getItems()) {
                // 报销类型
                item.setBxTypeName(BXTypeEnum.getEnumByKey(item.getBxType()));

                // 报销项目
                item.setBxProjectName(modelService.getCatalogName(item.getBxProject()));

                // 报销人（经办人）
                item.setBxPeopleCn(modelService.getUserTrueName(item.getBxPeople()));

                // 经办人
                item.setBxExtPersonCn(modelService.getManageName(item.getBxExtPerson()));

                // 报销状态
                item.setBxStatusName(BXStatusEnum.getEnumByKey(item.getBxStatus()));

                BxAmountReal = BxAmountReal.add(item.getRealBxAmount());

                // 获取当前审批环节
                if (item.getStopFlag() == 0 && item.getBxStatus() != -1 && item.getBxStatus() != 2 && item.getBxStatus() != 10) {
                    lineQuery = new WorkflowApplyLineDTOQuery();
                    lineQuery.setApplyId(item.getApplyId());
                    lineQuery.setIsCurrent(1);
                    lineDTO = applyLineService.getByQuery(lineQuery);
                    if (lineDTO != null) {
                        item.setApplyNodeSign(lineDTO.getNodeSign());
                        if (StringUtils.isNotBlank(lineDTO.getNodeDescription())) {
                            item.setApplyNodeTitle(lineDTO.getNodeDescription());
                        } else {
                            item.setApplyNodeTitle(lineDTO.getNodeTitle());
                        }
                    }
                }

                //查询子单
                childList = expenseService.getSplitOrderByRecursion(item.getId());
                for (TransportExpenseDTO child : childList) {
                    child.setBxTypeName(item.getBxTypeName());
                    child.setBxProjectName(item.getBxProjectName());
                    child.setBxPeopleCn(item.getBxPeopleCn());
                    child.setBxExtPersonCn(item.getBxExtPersonCn());
                    child.setBxStatusName(BXStatusEnum.getEnumByKey(child.getBxStatus()));
                }
                item.setChildList(childList);
            }
        }

        model.addAttribute("page", dataPage);
        model.addAttribute("PagePackage", PagePackage(dataPage.getPn(), dataPage.getStart(), dataPage.getPageSize(), dataPage.getTotalPages(), dataPage.getTotalItems()));
        model.addAttribute("dtoQuery", dtoQuery);
        model.addAttribute("BxAmountReal", BxAmountReal);

        modelService.getCatalogPage(model, 12, "bxprojectCatalogList");

        //报销日期
        if (StringUtils.isNotBlank(dtoQuery.getDaterange())) {
            String[] date = dtoQuery.getDaterange().split("~");
            if (date.length == 2) {
                model.addAttribute("startDate", date[0].trim());
                model.addAttribute("endDate", date[1].trim());
            }
        }

        //region 显示标题
        //报销类型：1司机费用 2采购报销 3配件报销 4维修报销 5综合报销 6借款申请 7费用支付
        String showTitle;
        String smallTitle;
        switch (dtoQuery.getBxType()) {
            case 6:
                showTitle = "借款申请";
                smallTitle = "借款";
                break;
            case 7:
                showTitle = "费用支付";
                smallTitle = "付款";
                break;
            default:
                showTitle = "未知";
                smallTitle = "未知";
                break;
        }
        model.addAttribute("showTitle", showTitle);
        model.addAttribute("smallTitle", smallTitle);
        //endregion

        return "erp/expense-borrow/index";
    }

    //endregion

    //region 编辑&保存

    /**
     * 编辑
     *
     * @param model  model模型
     * @param id     主键id
     * @param bxType 报销类型 1司机费用 2采购报销 3配件报销 4维修报销 5综合报销 6借款申请 7费用支付
     * @return vm
     */
    @RequestMapping(value = "/edit", method = RequestMethod.GET)
    public String edit(HttpServletRequest request, Model model, Integer id, Integer bxType) {
        if (id == null || id <= 0) {
            id = 0;
        }

        if (bxType == null || (bxType != 6 && bxType != 7)) {
            throw new RuntimeException("没查询到相关申请流程！");
        }

        String pin = AdminBaseClass.getPin(request);
        AnalysisManageDTO curr_obj = manageService.getFromCachePin(pin);
        TransportExpenseDTO obj;

        if (id > 0) {
            obj = expenseService.getById(id);
            obj.setBxPeopleCn(modelService.getUserTrueName(obj.getBxPeople()));
            obj.setReviewerCn(modelService.getUserTrueName(obj.getReviewer()));

        } else {
            obj = new TransportExpenseDTO();
            obj.setId(0);
            obj.setBxType(bxType);
            obj.setPurchaseType(0);
            obj.setPayWay(1);
            obj.setBxAmount(new BigDecimal(0));
            obj.setRealBxAmount(new BigDecimal(0));
            obj.setBxDate(new Date());
            obj.setPayDate(new Date());

            int uid = modelService.getUserIdByAdminId(curr_obj.getId());
            obj.setBxPeople(uid); //会员
            obj.setBxPeopleCn(curr_obj.getNickName());

            //复核人：获取部门负责人
            obj.setReviewerCn(modelService.getUserTrueName(obj.getReviewer()));

            String preTitle = "未知";

            //I.  如果是借款申请
            if (bxType == 6) {
                WorkflowBusinessDTO bDTO = businessService.getByEnName("borrow_apply");
                if (bDTO != null) {
                    obj.setBusinessId(bDTO.getId());
                }
                preTitle = "借款申请";
            }

            //II. 如果是费用支付
            if (bxType == 7) {
                WorkflowBusinessDTO bDTO = businessService.getByEnName("pay_fee");
                if (bDTO != null) {
                    obj.setBusinessId(bDTO.getId());
                }
                preTitle = "费用支付";
            }

            obj.setBxName(String.format("%s的（请填写具体申请信息）%s单", obj.getBxPeopleCn(), preTitle));
        }

        model.addAttribute("Obj", obj);

        //报销项目
        modelService.getCatalogPage(model, 12, "bxProjectList");

        //收款单位
        modelService.getCompayPage(model, 2);

        //付款单位
        modelService.getCompayPage(model, 7, null, "receivePayList");

        //付款方式
        model.addAttribute("receiveWayList", ReceiveWayEnum.getEnumList());

        //region 显示标题

        //报销类型：1司机费用 2采购报销 3配件报销 4维修报销 5综合报销 6借款申请 7费用支付
        String showTitle;
        String smallTitle;
        switch (bxType) {
            case 6:
                showTitle = "借款申请";
                smallTitle = "借款";
                break;
            case 7:
                showTitle = "费用支付";
                smallTitle = "付款";
                break;
            default:
                showTitle = "未知";
                smallTitle = "未知";
                break;
        }
        model.addAttribute("showTitle", showTitle);
        model.addAttribute("smallTitle", smallTitle);

        //endregion

        return "erp/expense-borrow/edit";
    }

    /**
     * 保存 ajax异步
     *
     * @param request sevelet请求
     * @param objDTO  实体类
     * @return json
     */
    @RequestMapping(value = "/saveEdit", method = RequestMethod.POST)
    @ResponseBody
    public String saveEditNotify(HttpServletRequest request, TransportExpenseDTO objDTO) {

        // 结果返回 结果至少包含一个操作状态和一条状态信息
        String result = "";
        Map<String, String> map = new HashMap<String, String>();

        //region 显示标题

        //报销类型：1司机费用 2采购报销 3配件报销 4维修报销 5综合报销 6借款申请 7费用支付
        String showTitle;
        switch (objDTO.getBxType()) {
            case 6:
                showTitle = "借款申请";
                break;
            case 7:
                showTitle = "费用支付";
                break;
            default:
                showTitle = "未知";
                break;
        }

        //endregion

        try {
            if (objDTO.getReviewer() == null || objDTO.getReviewer() <= 0) {
                map = OperateCode.CompositionResult(map, -10, "请填写报销复核人！");
                result = JSONUtils.toJSON(map);
                return result;
            }

            //报销项目必填
            if (objDTO.getBxProject() == null || objDTO.getBxProject() <= 0) {
                map = OperateCode.CompositionResult(map, -10, "请选择事由！");
                result = JSONUtils.toJSON(map);
                return result;
            }

            //必须选择报销流程
            if (objDTO.getBusinessId() == null || objDTO.getBusinessId() <= 0) {
                map = OperateCode.CompositionResult(map, -10, "请选择申请流程！");
                result = JSONUtils.toJSON(map);
                return result;
            }

            //日期
            objDTO.setBxDate(DateConvertUtils.strToShortDate(objDTO.getBxDateSr()));

            //审批ID
            Integer applyId = objDTO.getApplyId();

            //业务流程，不同业务有各自的流程
            String businessName = "";

            String pin = AdminBaseClass.getPin(request);
            AnalysisManageDTO curr_obj = manageService.getFromCachePin(pin);

            if (objDTO.getId() == null || objDTO.getId() <= 0) {

                //region STEP 01 伪事务 - 新增
                objDTO.setParentId(0);
                objDTO.setRealUseAmount(new BigDecimal(0));
                objDTO.setBxNo(GeneralUtils.GenTimeSeries(4, null, null));    //生成报销单号
                objDTO.setCarId(0);
                objDTO.setDriverId(0);
                objDTO.setReviewDate(DateConvertUtils.strToShortDate("1990-01-01"));
                objDTO.setReviewStatus(0);
                objDTO.setBxExtPerson(curr_obj.getId());
                objDTO.setBxStatus(0);
                objDTO.setRelationId(0);
                objDTO.setBookidsArray("");
                objDTO.setApplyId(0);
                objDTO.setAdminId(curr_obj.getId());
                objDTO.setCreateTime(new Date());
                objDTO.setStopFlag(0);
                objDTO.setDeleteFlag(0);

                objDTO = expenseService.insert(objDTO);

                if (objDTO == null || objDTO.getId() <= 0) {
                    //程序终止，返回失败信息
                    map = OperateCode.CompositionResult(map, -1);
                    result = JSONUtils.toJSON(map);
                    return result;
                }
                //endregion

                //region STEP 02 - 事务 - 生成审批流程

                //流程标题前缀
                Map<String, String> param = new HashMap<>();

                //A.【借款申请】
                if (objDTO.getBxType() == 6) {
                    businessName = "borrow_apply";
                    param.put("applyTitle", objDTO.getBxName().replace("单", ""));
                }

                //B.【费用支付】
                if (objDTO.getBxType() == 7) {
                    businessName = "pay_fee";
                    param.put("applyTitle", objDTO.getBxName().replace("单", ""));
                }

                //设定第一、二审批人
                //[改版后]审批人走的是会员系统
                param.put("firstExector", objDTO.getBxPeople() + "");
                param.put("secondExector", objDTO.getReviewer() + "");

                applyId = transactionService.createApplyWithout(businessName, "transport_expense", objDTO.getId(), objDTO.getBxExtPerson(), param);

                if (applyId > 0) {

                    //更新报销表中的applyid
                    TransportExpenseDTO updateDto = new TransportExpenseDTO();
                    updateDto.setId(objDTO.getId());
                    updateDto.setApplyId(applyId);
                    expenseService.updateInfoById(updateDto);

                } else {

                    // 审批流程生成失败
                    // 1. 将已生成的报销单设置为无效
                    expenseService.changeState(objDTO.getId(), 1);

                    //程序终止，返回失败信息
                    map = OperateCode.CompositionResult(map, -1);
                    result = JSONUtils.toJSON(map);
                    return result;
                }

                //endregion

            } else {

                //region 更新 只能更新个别信息
                TransportExpenseDTO update = new TransportExpenseDTO();
                update.setId(objDTO.getId());
                update.setBxName(objDTO.getBxName());
                update.setBxProject(objDTO.getBxProject());
                update.setRealBxAmount(objDTO.getRealBxAmount());
                update.setBxPeople(objDTO.getBxPeople());
                update.setReviewer(objDTO.getReviewer());
                update.setBxDate(objDTO.getBxDate());
                update.setCompanyId(objDTO.getCompanyId());
                update.setLinkName(objDTO.getLinkName());
                update.setLinkMobile(objDTO.getLinkMobile());
                update.setPayCompanyId(objDTO.getPayCompanyId());
                update.setPayWay(objDTO.getPayWay());
                update.setRemark(objDTO.getRemark());

                Boolean isNext = expenseService.updateInfoById(update);

                if (isNext) {

                    //设置第1审批人和每2审批人
                    if (objDTO.getApplyId() > 0) {
                        Integer firstExector = objDTO.getBxPeople();
                        Integer secondExector = objDTO.getReviewer();

                        Map<Integer, Integer> replaceMap = new HashMap<>();
                        replaceMap.put(1, firstExector);
                        replaceMap.put(2, secondExector);
                        transactionService.setExector(objDTO.getApplyId(), replaceMap);
                    }

                } else {
                    //操作失败
                    map = OperateCode.CompositionResult(map, -1);
                    result = JSONUtils.toJSON(map);
                    return result;
                }
                //endregion
            }

            //region 操作完成后判断金额是否大于300，如果大于300则启用经理审批
            businessNodeService.handleJudgeApply(businessName, 1, objDTO.getRealBxAmount(), applyId);
            //endregion

            //region *** 更新信息完毕记录操作日志 ***
            logService.insertSimple(1, 45, objDTO.getId(), 2,
                    "更新" + showTitle + "单",
                    FastJsonUtils.toJSONString(objDTO),
                    curr_obj.getId(),
                    IpUtils.getClientIp(request),
                    SystemUtils.getBrowserInfo(request));
            //endregion

            //操作成功 结果返回
            map = OperateCode.CompositionResult(map, 1, showTitle + "单生成成功！");
            result = JSONUtils.toJSON(map);
            return result;

        } catch (Exception e) {
            //清空map
            map.clear();
            map = OperateCode.CompositionResult(map, -1);
            result = JSONUtils.toJSON(map);
            return result;
        }
    }
    //endregion

}